package com.znyj.cloud.device.async;

import com.znyj.cloud.chain.util.CheckUtil;
import com.znyj.cloud.chain.util.SpringContextHelper;
import com.znyj.cloud.device.constant.SysConstant;
import com.znyj.cloud.device.entity.ReportEntity;
import com.znyj.cloud.device.entity.TaskEntity;
import com.znyj.cloud.device.pack.AtomicValues;
import com.znyj.cloud.device.pack.TaskSendPackage;
import com.znyj.cloud.device.service.ReportService;
import com.znyj.cloud.device.service.TaskService;
import com.znyj.cloud.device.task.ControlTaskMapping;
import com.znyj.cloud.device.task.model.ControlTaskModel;
import com.znyj.cloud.device.util.ExceptionUtil;
import org.apache.log4j.Logger;

import java.sql.Timestamp;
import java.util.List;


/**
 * Created by gaoliwei02 on 17/6/1.
 */
//异步操作心跳包数据库
public class ReportAsync implements Runnable {
    private static final Logger logger = Logger.getLogger(ReportAsync.class);
    private ReportEntity reportEntity;
    private int op;

    //构造
    public ReportAsync(ReportEntity reportEntity, int op) {
        this.reportEntity = reportEntity;
        this.op = op;
    }

    @Override
    public void run() {
        ReportService reportService = SpringContextHelper.getBean(ReportService.class);
        TaskService taskervice = SpringContextHelper.getBean(TaskService.class);

        String deviceId = reportEntity.getDeviceId();
        switch (op) {
            case SysConstant.CDB_OP.INSERT_FIRST: {
                int num = reportService.getDeviceIdNumber(deviceId);
                if (num > 1) {
                    //多于1条则删除所有再插入1条
                    reportService.deleteDeviceId(deviceId);
                    reportService.insertReport(reportEntity);
                } else if (num == 1) {
                    //以前就只有1条更新这一条
                    reportService.updateCommonInfo(reportEntity);
                } else {
                    //没有历史记录插入1条
                    reportService.insertReport(reportEntity);
                }
            }
            break;

            case SysConstant.CDB_OP.UPDATE_OFFLINE: {
                reportService.updateOnlineStatus(deviceId, reportEntity.getOnlineStatus());
            }
            break;

            case SysConstant.CDB_OP.UPDATE_REPORT: {
                {
                    Timestamp createTime = new Timestamp(System.currentTimeMillis());
                    long orderId = reportService.getChannalAOrderId(deviceId);

                    //设备上:有订单\当两个status0\，解决3分钟自动关闭
                    //方案：强制卸载订单，insert DB task 0 autoclose 不发送命令
                    if (orderId > 0 && (reportEntity.getStatusA() == 0) && (reportEntity.getStatusB() == 0)) {

                        int tmp = ExceptionUtil.addAutoCloseMap(deviceId);
                        if (tmp >= SysConstant.AUTOCLOSE_CNT) {
                            ExceptionUtil.romoveAutoCloseMap(deviceId);

                            long tempOrderId = AtomicValues.incOrderId();
                            TaskEntity taskEntity = new TaskEntity();
                            taskEntity.setUserId("auto close");
                            taskEntity.setDeviceId(deviceId);
                            taskEntity.setOrderId(tempOrderId);
                            taskEntity.setDurationSec(0);
                            taskEntity.setSendStatus(0);
                            taskEntity.setControlMsg("virtual close AB");
                            taskEntity.setUserLocation("");
                            taskEntity.setCreateTime(createTime);
                            taskEntity.setExecuteResult("auto close");
                            taskervice.insertTask(taskEntity);

                            reportService.updateABInfo(deviceId, new Timestamp(SysConstant.DEFAULT_TIME), 0, "", 0, new Timestamp(SysConstant.DEFAULT_TIME), 0, "", 0);
                            logger.info("autoCheck of auto close: virtual close all:");
                        } else {
                            logger.info("autoCheck of auto close: count to close:{}" + tmp);
                        }
                    }

                    //设备上没有挂载订单，但是设备A或B已经打开，主要解决发送控制包失败后丢控制回包但执行
                    //方案：发送close订单，put taskMap task cdbclose
                    //貌似只有发送控制失败出现没有订单只有status1，close正常发送并收到回包才清除order，并且肯定已经执行close，下一次上传的心跳绝对是Status0
                    else if (orderId == 0 && (reportEntity.getStatusA() == 1 || reportEntity.getStatusB() == 1)) {
                        int tmp = ExceptionUtil.addPacketLossMap(deviceId);
                        if (tmp >= SysConstant.PACKETLOSS_CNT) {
                            ExceptionUtil.romovePacketLossMap(deviceId);

                            ControlTaskMapping controlTaskMapping = SpringContextHelper.getBean(ControlTaskMapping.class);

                            long tempOrderIdA = AtomicValues.incOrderId();
                            long tempOrderIdB = AtomicValues.incOrderId();

                            TaskEntity taskEntityA = new TaskEntity();
                            taskEntityA.setUserId("packet loss");
                            taskEntityA.setDeviceId(deviceId);
                            taskEntityA.setOrderId(tempOrderIdA);
                            taskEntityA.setDurationSec(0);
                            taskEntityA.setSendStatus(0);
                            taskEntityA.setControlMsg("cdbaclose");
                            taskEntityA.setUserLocation("");
                            taskEntityA.setCreateTime(createTime);
                            taskEntityA.setExecuteResult("packet loss");
                            taskervice.insertTask(taskEntityA);

                            TaskSendPackage taskSendPackageA = new TaskSendPackage(taskEntityA);
                            ControlTaskModel controlTaskModelA = new ControlTaskModel(taskSendPackageA, 0);
                            controlTaskMapping.add(deviceId, controlTaskModelA);
                            logger.info("autoCheck of packet loss: close all Aport:" + taskSendPackageA.reportJson());

                            TaskEntity taskEntityB = new TaskEntity();
                            taskEntityB.setUserId("packet loss");
                            taskEntityB.setDeviceId(deviceId);
                            taskEntityB.setOrderId(tempOrderIdB);
                            taskEntityB.setDurationSec(0);
                            taskEntityB.setSendStatus(0);
                            taskEntityB.setControlMsg("cdbbclose");
                            taskEntityB.setUserLocation("");
                            taskEntityB.setCreateTime(createTime);
                            taskEntityB.setExecuteResult("packet loss");
                            taskervice.insertTask(taskEntityB);

                            TaskSendPackage taskSendPackageB = new TaskSendPackage(taskEntityB);
                            ControlTaskModel controlTaskModelB = new ControlTaskModel(taskSendPackageB, 2);
                            controlTaskMapping.add(deviceId, controlTaskModelB);
                            logger.info("autoCheck of packet loss: close all Aport:" + taskSendPackageB.reportJson());
                        } else {
                            logger.info("autoCheck of packet loss: count to close:{}" + tmp);
                        }
                    } else {
                        ExceptionUtil.romoveAutoCloseMap(deviceId);
                        ExceptionUtil.romovePacketLossMap(deviceId);
                    }

                }
                reportService.updateCommonInfo(reportEntity);
            }
            break;

            case SysConstant.CDB_OP.UPDATE_OTA_TIME: {
                reportService.updateOtaTime(deviceId, reportEntity.getOtaTime());
            }
            break;

            //设备注册时查看是否有设备可以绑定
            case SysConstant.CDB_OP.UPDATE_POIID: {
                List<Long> bindPoiid = reportService.findBindPoiid(deviceId);
                if (bindPoiid.size() == 1) {
                    reportService.updatePoiid(bindPoiid.get(0), deviceId);
                } else if (bindPoiid.size() > 1) {
                    //一个deviceId有多个POIID绑定
                    reportService.updatePoiid(-1L, deviceId);
                    logger.error(CheckUtil.monitorReport(SysConstant.ERROR_CODE.BIND_MULI_POIID, "POIID:" + bindPoiid.toString(), Long.parseLong(deviceId)));
                } else {
                    //此设备没有可绑定的POIID
                    logger.error(CheckUtil.monitorReport(SysConstant.ERROR_CODE.BIND_NULL_POIID, "POIID:" + bindPoiid.toString(), Long.parseLong(deviceId)));
                }
            }
            break;
        }
    }
}
